home *** CD-ROM | disk | FTP | other *** search
- /* Copyright © 1989 Farallon Computing, Inc */
-
- #include "Sound.h"
-
- #define NIL 0
- #define Snd2HeaderSize 36
- #define K 1024 /* 1024 bytes per K */
-
- void InitMac( void);
- short Record( Handle, short);
- Handle GetBigHandle( short);
-
- long Mono22Khz( char*, Ptr, char*, long);
- void BuildSoundHeader( Handle);
- void FillInNumSample( Handle, long);
- void Interrupts( short );
- void SCCPort( short, char**, char** );
- void SCCPoke( char*, short, short );
- void SCCInit( char*);
- void BuildFlipTable( char*);
- short Flip( short);
-
- /*
- ** Geneal function to initialize the managers
- */
- void InitMac()
- {
- register short i;
- Ptr p;
-
- asm
- {
- MOVE.L SP,A0 ; current stack pointer to A0
- SUB #0x4000,A0 ; allow it to expand 16K lower
- MOVE.L A0,p
- }
-
- SetApplLimit( p );
- MaxApplZone(); /* grow the Application's heap zone to its limit */
-
- /*
- ** Initialize all managers through the Window Manager here,
- ** rather than in our initialization segment, because
- ** InitWindows allocates non-relocatables. We don't want
- ** those non-relocatables allocated above the initialization
- ** segment which will be loaded low by the 64K ROM segment
- ** loader. The remaining managers are initialized from our
- ** initialization segment.
- */
- InitGraf( &thePort );
- InitFonts();
- InitWindows();
-
- /*
- Call MoreMasters here because it allocates non-relocatables.
- */
- for (i=0;i<6;i++) MoreMasters();
- InitMenus();
- InitDialogs( NIL );
- TEInit();
-
- InitCursor(); /* arrow cursor */
- }
-
- /*
- ** Records a sound into the sound Handle
- ** Builds a header around the sound to make it a snd2 format
- ** If recording fails, returns recordErr ( = -1)
- ** Recording stops when memory runs out OR the mouse
- ** is clicked (or moved on MacII or more recent models)
- **
- ** We record a mono sound at 22Khz
- */
- short Record( soundHandle, whichPort)
- Handle soundHandle;
- short whichPort;
- {
- char* writePort;
- char* readPort;
- unsigned char table[256 + 1];
- long size = GetHandleSize( soundHandle);
- long len;
-
- /* the handle is too small to even accomodate the header */
- if (size < Snd2HeaderSize)
- return( recordErr);
-
- /* initialize MacRecorder */
- SCCPort( whichPort, &readPort, &writePort );
- SCCInit( writePort );
- BuildFlipTable( (char *)table );
-
- BuildSoundHeader( soundHandle); /* builds snd2 header */
-
- HLock( soundHandle);
- Interrupts( false ); /* turn interrupts off */
- /* actually record it here */
- len = Mono22Khz( readPort, (Ptr)(*soundHandle + Snd2HeaderSize),
- (char *)table, size - Snd2HeaderSize );
- Interrupts( true ); /* turn interrupts back on */
- HUnlock( soundHandle);
-
- if (len == -1)
- {
- /* could not record */
- return( recordErr);
- }
- else
- {
- /* fills header with # samples */
- FillInNumSample( soundHandle, len);
- SetHandleSize( soundHandle, len + Snd2HeaderSize); /* shrink the handle */
- return( noErr);
- }
- }
-
- /*
- ** Allocate the largest possible handle
- ** while leaving the given number of K
- ** available
- */
- Handle GetBigHandle( leaveThis)
- short leaveThis;
- {
- long maxLength;
- Handle reserveHandle;
- Handle bigHandle;
-
- reserveHandle = NewHandle( leaveThis*K);
- if (reserveHandle == 0)
- return( 0); /* we don't even HAVE the memory we want to reserve */
-
- /* allocate largest possible handle now */
- maxLength = CompactMem( 0x7FFFFFFFL);
- bigHandle = NewHandle( maxLength);
-
- DisposHandle( reserveHandle); /* release memory we were reserving */
- return( bigHandle);
- }
-
- static void SCCInit( scc )
- char *scc;
- {
- Interrupts( false ); /* turn off interupts */
- SCCPoke(scc,9,2); /* NV only */
- SCCPoke(scc,4,12); /* 2 stop bits, Async, x16 clock mode */
- SCCPoke(scc,1,1); /* no Rx/Tx Int, Ext Int ON (mouse) */
- SCCPoke(scc,3,193); /* initialize receiver, 8bits */
- SCCPoke(scc,5,122); /* 8bits/char, send break(for other hardware!), Tx enable */
- SCCPoke(scc,11,48); /* use TRxC as receiver clock */
- SCCPoke(scc,14,1); /* BR enable, nothing else */
- SCCPoke(scc,15,8); /* Interrupt on CD changes (mouse), turn off CTS interrupt */
- SCCPoke(scc,64,64); /* Reset Rx CRC */
- SCCPoke(scc,9,10); /* initialize master interrupt and NV */
- Interrupts( true ); /* turn on interrupts */
- }
-
- static void SCCPoke( scc, reg, value )
- char *scc;
- short reg, value;
- {
- *scc = reg;
- *scc = value;
- }
-
-
- static void SCCPort( whichPort, read, write )
- short whichPort;
- char **read, **write;
- {
- *read = SCCRd;
- *write = SCCWr;
- if (whichPort == modemPort)
- {
- *read += 2;
- *write += 2;
- }
- }
-
- /*
- ** Data comes out of the MacRecorder with the bits of each
- ** byte in the wrong order. So, we must flip each byte to
- ** get it in the right order. Instead of doing this on the
- ** fly, we build a table that has an entry for each value
- ** a byte can have and which gives the flip value for each
- ** entry
- */
- static void BuildFlipTable( p )
- register char *p;
- {
- register short i;
-
- for (i=0; i<256; i++)
- p[i] = Flip(i);
- }
-
- /* flips a byte (byte 0 becomes byte 7, etc.) */
- static short Flip( x )
- short x;
- {
- asm
- {
- MOVEM.L D1-D2,-(A7) ; save on stack
- MOVE x,D1 ; value we want to flip
- MOVEQ #7,D2 ; loop though 8 bits
- MOVEQ #0,D0 ; our result
- @0
- ROXL.B #1,D1 ; get bit n from source
- ROXR.B #1,D0 ; roll into MSB of dest
- DBRA D2,@0 ; are we done?
- ; D0 contains flipped value
- MOVEM.L (A7)+,D1-D2 ; retrieve saved registers
- }
- }
-
- /*
- ** Record a Mono sound at 22KHz
- ** len = maximum length for the sound
- */
- static long Mono22Khz(fromWhere, outBuff, flipTable, len )
- char* fromWhere;
- Ptr outBuff;
- char* flipTable;
- long len;
- {
- asm
- {
- MOVEM.L A2-A4/D2-D7,-(SP) ; save regs
-
- MOVE.L fromWhere,A4 ; get SCC
- MOVE.L outBuff,A3 ; get dest buffer
- MOVE.L flipTable,A2 ; get trans table
- MOVE.L len,D6 ; get buffer max
-
- MOVEQ #-1,D0 ; result code - assume the worst
-
- MOVE.L VIA,A0 ; mouse address from VIA
- MOVEQ #0,D2 ; byte holder
- MOVE.L D6,D1 ; save byte count
- @reset
- MOVE #50000,D7 ; watchdog timer
- @loop
- SUBQ.L #1,D7 ; decrement watchdog
- BMI.S @timeOut
-
- BTST #3,(A0) ; mouse button abort?
- BEQ.S @exit
-
- BTST #0,(A4) ; test and wait for data from SCC
- BEQ.S @loop ; not yet
-
- MOVE.B 4(A4),D2 ; get the data
- MOVE.B 0(A2,D2),(A3)+ ; stuff away
-
- SUBQ.L #1,D6
- BNE.S @reset
- @exit
- SUB.L D6,D1 ; get actual byte count
- MOVE.L D1,D0 ; and return it
- @timeOut
- MOVEM.L (SP)+,A2-A4/D2-D7 ; restore regs
- }
- }
-
-
- /*
- ** Takes a handle and fills in the memory at the handle
- ** with a Snd2 resource header
- */
- static void BuildSoundHeader( soundHandle)
- Handle soundHandle;
- {
- asm
- {
- MOVE.L A0, -(A7) ; save regsiter
- MOVE.L soundHandle, A0 ; handle to data
- MOVE.L (A0),A0 ; dereference
- MOVE #2,(A0) ; format 2 resource
- MOVE #1,4(A0) ; 1 sound command to follow
-
- /* first command, 8 bytes in length */
- MOVE #0x8051,6(A0) ; bufferCmd, high bit on to indicate sound
- ; data included
- MOVE #0,8(A0) ; bufferCmd param1
- MOVE.L #20,10(A0) ; bufferCmd param2,
- ; offset to sound header
-
- /* sampled sound header used in a soundCmd and bufferCmd */
- MOVE.L #0,14(A0) ; ptr to data
- ; (it follows immediately)
- MOVE.L #0,18(A0) ; number of samples
- ; (gets filled in later)
- MOVE.L #0x56EE8BA3,22(A0) ; sampling rate (22kHz)
- MOVE.L #0,26(A0) ; starting of sample's loop point
- MOVE.L #0,30(A0) ; ending of sample's loop point
- MOVE.B #0,34(A0) ; standard sample encoding
- MOVE.B #0x3C,35(A0) ; base note (middle C)
-
- MOVE.L (A7)+,A0 ; restore A0
- }
- /* sound should start at byte 36 */
- }
-
- static void FillInNumSample( soundHandle, numSamples)
- Handle soundHandle;
- long numSamples;
- {
- asm
- {
- MOVE.L A0,-(A7) ; save A0
- MOVE.L soundHandle,A0 ; handle to data
- MOVE.L (A0),A0 ; deref
- MOVE.L numSamples,18(A0) ; fill it in
- MOVE.L (A7)+,A0 ; restore A0
- }
- }
-
-
- static void Interrupts( setEm )
- short setEm;
- {
- asm
- {
- MOVE setEm(A6),D0
- BNE.S @0
-
- ORI #0x0700,SR ; off
- BRA.S @1
- @0
- ANDI #0xF8FF,SR ; on
- @1
- }
- }
-
-